#include "dlgqtdeplus.h"
#include "ui_dlgqtdeplus.h"
#include <QSettings>
#include <QDir>
#include <QFileInfo>
#include <QDateTime>
#include <QFileDialog>
#include <QProcess>
#include <QDebug>
#include <QRegularExpression>
#include <QScrollBar>
DlgQtDeplus::DlgQtDeplus(QWidget *parent)
	: QDialog(parent)
	, ui(new Ui::DlgQtDeplus)
	, m_pMsgMod (new QStandardItemModel(this))
{
	ui->setupUi(this);
	ui->listView_msg->setModel(m_pMsgMod);
	loadIni();
	setWindowFlag(Qt::WindowMinMaxButtonsHint);
}

DlgQtDeplus::~DlgQtDeplus()
{
	delete ui;
}


void DlgQtDeplus::on_pushButton_run_clicked()
{
	if (!running)
	{
		stopcmd = false;
		running = true;
	}
	else
	{
		stopcmd = true;
		return;
	}
	ui->pushButton_run->setText("&Stop");
	saveIni();
	//Set env
	//Change CurrentDir
	QDir dir(ui->lineEdit_targetFolder->text());
	dir.setCurrent(dir.absolutePath());

	qputenv("QT_PLUGIN_PATH",ui->lineEdit_targetFolder->text().toUtf8());

	QString rawPath = qgetenv("PATH");
	QString newPath = ui->lineEdit_path_front->text();
	if (newPath.size())
		newPath += ";";
	newPath += rawPath;
	newPath += ";";
	if (ui->lineEdit_path_back->text().size())
		newPath += ui->lineEdit_path_back->text();
	qputenv("PATH",newPath.toUtf8());
	run_deployqt();
	run_ldd();
	int cnt = 0;
	while ((!stopcmd) &&run_ldd())
	{
		showMsg(tr("Running %1 times.").arg(++cnt));
		QCoreApplication::processEvents();
	}

	//recover
	qputenv("PATH",rawPath.toUtf8());
	showMsg("Finished!");
	running = false;
	ui->pushButton_run->setText("&Run");
}

void DlgQtDeplus::scrollPlainTextToBtm()
{
	ui->plainTextEdit_out->moveCursor(QTextCursor::End, QTextCursor::MoveAnchor);
	ui->plainTextEdit_out->verticalScrollBar()->setValue(ui->plainTextEdit_out->verticalScrollBar()->maximum());
}

int DlgQtDeplus::run_deployqt()
{
	//Enum all exe in target folder
	QFileInfoList lstExec;
	enumAllExes(ui->lineEdit_targetFolder->text(),&lstExec);

	QStringList lstExtra = ui->lineEdit_extra_folders->text().split(";",Qt::SkipEmptyParts);
	foreach (QString dirExtra,lstExtra)
	{
		if (stopcmd)
			break;
		enumAllExes(dirExtra,&lstExec);
	}
	ui->progressBar_bar->setRange(0,1000);
	ui->plainTextEdit_out->clear();
	int c = 0;
	foreach(QFileInfo info, lstExec)
	{
		if (stopcmd)
			break;		
		++c;
		ui->progressBar_bar->setValue(c*1000/lstExec.size());
		QProcess * call_process = new QProcess(this);
		call_process->setProgram("windeployqt.exe");
		QStringList args;
		args<<"--dir";
		args<<ui->lineEdit_targetFolder->text();
		args<<info.absoluteFilePath();
		call_process->setArguments(args);
		showMsg("windeployqt "+info.absoluteFilePath());
		ui->plainTextEdit_out->insertPlainText("\nwindeployqt "+info.absoluteFilePath());
		ui->plainTextEdit_out->insertPlainText("\n=========================\n");
		connect(call_process,&QProcess::readyReadStandardOutput,[call_process,this]()->void{
			ui->plainTextEdit_out->insertPlainText(QString::fromUtf8(call_process->readAllStandardOutput()));
			scrollPlainTextToBtm();
			QCoreApplication::processEvents();
		});
		connect(call_process,&QProcess::readyReadStandardError,[call_process,this]()->void{
			ui->plainTextEdit_out->insertPlainText(QString::fromUtf8(call_process->readAllStandardError()));
			scrollPlainTextToBtm();
			QCoreApplication::processEvents();
		});
		call_process->start();
		call_process->waitForStarted();
		call_process->waitForFinished();
		showMsg("windeployqt6 "+info.absoluteFilePath());
		ui->plainTextEdit_out->insertPlainText("\nwindeployqt6 "+info.absoluteFilePath());
		ui->plainTextEdit_out->insertPlainText("\n=========================\n");
		scrollPlainTextToBtm();
		call_process->setProgram("windeployqt6.exe");
		call_process->start();
		call_process->waitForStarted();
		call_process->waitForFinished();

		call_process->deleteLater();
	}

	return 0;
}

int DlgQtDeplus::run_ldd()
{
	static QRegularExpression exp("[\\ \\n\\r\\=\\>)()]");
	scrollPlainTextToBtm();
	QFileInfoList lstExec;
	enumAllExes(ui->lineEdit_targetFolder->text(),&lstExec);
	QStringList lstExtra = ui->lineEdit_extra_folders->text().split(";",Qt::SkipEmptyParts);
	foreach (QString dirExtra,lstExtra)
	{
		enumAllExes(dirExtra,&lstExec);
	}
	int cp = 0;
	QFileInfo infod(ui->lineEdit_targetFolder->text());
	QString pathM2 = ui->lineEdit_msys2->text().replace('\\','/').trimmed().toLower();
	ui->progressBar_bar->setRange(0,1000);
	int c = 0;
	QString cmdldd = ui->comboBox_ntldd->currentText();
	foreach(QFileInfo info, lstExec)
	{
		if (stopcmd)
			break;
		++c;
		ui->progressBar_bar->setValue(c*1000/lstExec.size());
		QProcess * call_process = new QProcess(this);
		call_process->setProgram(cmdldd);
		QStringList args;
		args<<info.absoluteFilePath();
		call_process->setArguments(args);
		call_process->start();
		call_process->waitForStarted();
		call_process->waitForFinished();
		showMsg(cmdldd+" "+info.absoluteFilePath());
		ui->plainTextEdit_out->insertPlainText("\n"+cmdldd+" "+info.absoluteFilePath());
		ui->plainTextEdit_out->insertPlainText("\n=========================\n");
		if (call_process->bytesAvailable())
		{
			QString str = QString::fromUtf8(call_process->readAllStandardOutput());
			ui->plainTextEdit_out->insertPlainText(str);
			scrollPlainTextToBtm();
			QStringList lstDeps = str.split(exp);
			foreach(QString dep, lstDeps)
			{
				QString lcdep = dep.toLower().replace('\\','/');
				if (lcdep.startsWith("/ucrt64/")
					||lcdep.startsWith("/mingw64/")
					||lcdep.startsWith("/mingw32/")
					||lcdep.startsWith("/clang32/")
					||lcdep.startsWith("/clang64/")
					||lcdep.startsWith("/usr/bin")
					||lcdep.startsWith("/bin")					
					)
				{
					QFileInfo info(pathM2+lcdep);
					QString tar(infod.absoluteFilePath()+"/"+info.fileName());
					QFile file(pathM2+lcdep);
					if (file.copy(tar))
						++cp;
					else
						showMsg(file.errorString());
				}
				else if (lcdep.startsWith(pathM2+"/m")
						   ||lcdep.startsWith(pathM2+"/u")
						   ||lcdep.startsWith(pathM2+"/c")
						   ||lcdep.startsWith(pathM2+"/b")
						   ||lcdep.startsWith(pathM2+"m")
						   ||lcdep.startsWith(pathM2+"u")
						   ||lcdep.startsWith(pathM2+"c")
						   ||lcdep.startsWith(pathM2+"b"))
				{
					QFileInfo info(lcdep);
					QString tar(infod.absoluteFilePath()+"/"+info.fileName());
					QFile file(lcdep);
					if (file.copy(tar))
						++cp;
					else
						showMsg(file.errorString());
				}
			}
		}
		call_process->deleteLater();
	}

	return cp;
}

void DlgQtDeplus::on_toolButton_targetFolder_clicked()
{
	QString lastFolder = ui->lineEdit_targetFolder->text();
	QString currFolder = QFileDialog::getExistingDirectory(this,tr("select folder"),lastFolder);
	if (currFolder.length()>0)
		ui->lineEdit_targetFolder->setText(currFolder);
	saveIni();
}


void DlgQtDeplus::on_toolButton_extra_folders_clicked()
{
	QSettings settings(QCoreApplication::applicationFilePath()+".ini",QSettings::IniFormat);
	QString lastFolder = settings.value("history/extra_folder",".").toString();
	QString currFolder = QFileDialog::getExistingDirectory(this,tr("select folder"),lastFolder);
	if (currFolder.length()>0)
	{
		QString old = ui->lineEdit_extra_folders->text();
		if (old.length())
			old += ";";
		old += currFolder;
		ui->lineEdit_extra_folders->setText(old);
		settings.setValue("history/extra_folder",currFolder);
	}
	saveIni();
}


void DlgQtDeplus::on_toolButton_path_front_clicked()
{
	QString lastFolder = ui->lineEdit_path_front->text();
	QString currFolder = QFileDialog::getExistingDirectory(this,tr("select folder"),lastFolder);
	if (currFolder.length()>0)
		ui->lineEdit_path_front->setText(currFolder);
	saveIni();
}


void DlgQtDeplus::on_toolButton_path_back_clicked()
{
	QString lastFolder = ui->lineEdit_path_back->text();
	QString currFolder = QFileDialog::getExistingDirectory(this,tr("select folder"),lastFolder);
	if (currFolder.length()>0)
		ui->lineEdit_path_back->setText(currFolder);
	saveIni();
}



void DlgQtDeplus::loadIni()
{
	QSettings settings(QCoreApplication::applicationFilePath()+".ini",QSettings::IniFormat);
	ui->lineEdit_targetFolder->setText(settings.value("ui/lineEdit_targetFolder",ui->lineEdit_targetFolder->text()).toString());
	ui->lineEdit_extra_folders->setText(settings.value("ui/lineEdit_extra_folders",ui->lineEdit_extra_folders->text()).toString());
	ui->lineEdit_path_back->setText(settings.value("ui/lineEdit_path_back",ui->lineEdit_path_back->text()).toString());
	ui->lineEdit_path_front->setText(settings.value("ui/lineEdit_path_front",ui->lineEdit_path_front->text()).toString());
	ui->lineEdit_msys2->setText(settings.value("ui/lineEdit_msys2",ui->lineEdit_msys2->text()).toString());
	ui->comboBox_ntldd->setCurrentText(settings.value("ui/comboBox_ntldd",ui->comboBox_ntldd->currentText()).toString());

}
void DlgQtDeplus::saveIni()
{
	QSettings settings(QCoreApplication::applicationFilePath()+".ini",QSettings::IniFormat);
	settings.setValue("ui/lineEdit_targetFolder",ui->lineEdit_targetFolder->text());
	settings.setValue("ui/lineEdit_extra_folders",ui->lineEdit_extra_folders->text());
	settings.setValue("ui/lineEdit_path_front",ui->lineEdit_path_front->text());
	settings.setValue("ui/lineEdit_path_back",ui->lineEdit_path_back->text());
	settings.setValue("ui/lineEdit_msys2",ui->lineEdit_msys2->text());
	settings.setValue("ui/comboBox_ntldd",ui->comboBox_ntldd->currentText());

}
void  DlgQtDeplus::showMsg(QString m)
{
	m_pMsgMod->appendRow(new QStandardItem(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")+">"+m));
	if (m_pMsgMod->rowCount()>1024)
		m_pMsgMod->removeRows(0,m_pMsgMod->rowCount()-1024);
	ui->listView_msg->scrollToBottom();
	QCoreApplication::processEvents();

}
void DlgQtDeplus::enumAllExes(QString folder,QFileInfoList * pLst)
{
	if (stopcmd)
		return;
	QDir dir_target(folder);
	QStringList lstExecTypes;
	lstExecTypes << "*.dll";
	lstExecTypes << "*.exe";
	QFileInfoList lstExec = dir_target.entryInfoList(lstExecTypes);
	pLst->append(lstExec);

	lstExecTypes.clear();
	lstExecTypes<<"*";
	lstExecTypes<<"*.*";
	lstExec = dir_target.entryInfoList(lstExecTypes);
	foreach(QFileInfo info, lstExec)
	{
		if (stopcmd)
			break;
		if (info.isDir())
		{
			if (!info.fileName().startsWith("."))
			{
				enumAllExes(info.absoluteFilePath(),pLst);
			}
		}
	}
}

void DlgQtDeplus::on_toolButton_msys2_clicked()
{
	QString lastFolder = ui->lineEdit_msys2->text();
	QString currFolder = QFileDialog::getExistingDirectory(this,tr("select folder"),lastFolder);
	if (currFolder.length()>0)
		ui->lineEdit_msys2->setText(currFolder);
	saveIni();
}

